"""
聊天API端点模块

提供聊天相关的RESTful API接口，包括：
1. 发送消息（流式/非流式）
2. 创建对话
3. 获取消息历史
4. RAG聊天
5. 对话摘要

主要功能：
- 支持流式和非流式响应
- 多轮对话管理
- 会话状态控制
- 错误处理和验证
- 统一的响应格式

作者: LLM Chat System
版本: 1.0.0
"""

from typing import List
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
import json
from app.core.logging_config import get_logger

# 导入数据库依赖
from app.database import get_db
# 导入聊天服务
from app.services.chat_service import ChatService
# 导入数据模式
from app.schemas.chat import (
    ChatRequest, ChatResponse, ChatStreamResponse,
    ConversationCreateRequest, ConversationCreateResponse,
    MessageHistoryRequest, MessageHistoryResponse,
    RAGChatRequest, RAGChatResponse
)
# 导入认证依赖
from app.api.v1.endpoints.auth import get_current_user
from app.models.user import User

# 创建API路由器
router = APIRouter()
# 创建聊天服务实例
chat_service = ChatService()
# 创建日志记录器
logger = get_logger(__name__)


@router.post("/send", response_model=ChatResponse)
async def send_message(
    request: ChatRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    发送消息接口
    
    处理用户发送的消息，调用大模型生成回复。
    支持非流式响应，返回完整的回复内容。
    
    Args:
        request: 聊天请求，包含对话ID、消息内容等
        db: 数据库会话，通过依赖注入获取
        current_user: 当前登录用户，通过JWT token验证
        
    Returns:
        ChatResponse: 包含回复内容、消息ID、token统计等
        
    Raises:
        HTTPException: 当对话不存在或处理失败时抛出
    """
    try:
        logger.info(f"收到发送消息请求: 用户ID={current_user.id}, 对话ID={request.conversation_id}, 消息长度={len(request.message)}")
        
        # 从JWT token中获取用户ID
        user_id = current_user.id
        
        if request.stream:
            logger.warning("流式请求使用了错误的端点")
            raise HTTPException(
                status_code=400,
                detail="流式请求请使用 /stream 端点"
            )
        
        result = await chat_service.send_message(
            db=db,
            conversation_id=request.conversation_id,
            user_id=user_id,
            message=request.message,
            model_settings=request.model_settings.dict() if request.model_settings else None,
            knowledge_base_id=getattr(request, 'knowledge_base_id', None),
            model_config_id=getattr(request, 'model_config_id', None)
        )
        
        logger.info(f"消息发送成功: 对话ID={request.conversation_id}, 回复长度={len(result.get('message', ''))}")
        return ChatResponse(**result)
        
    except ValueError as e:
        logger.error(f"发送消息参数错误: {str(e)}")
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"发送消息失败: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"发送消息失败: {str(e)}")


@router.post("/stream")
async def send_message_stream(
    request: ChatRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """发送消息（流式响应）"""
    try:
        # 从JWT token中获取用户ID
        user_id = current_user.id
        
        logger.info(f"收到流式消息请求: 对话ID={request.conversation_id}, 流式={request.stream}")
        
        if not request.stream:
            raise HTTPException(
                status_code=400,
                detail="非流式请求请使用 /send 端点"
            )
        
        async def generate():
            try:
                # 直接迭代流式响应生成器
                async for chunk in chat_service.send_message_stream(
                    db=db,
                    conversation_id=request.conversation_id,
                    user_id=user_id,
                    message=request.message,
                    model_settings=request.model_settings.dict() if request.model_settings else None,
                    knowledge_base_id=getattr(request, 'knowledge_base_id', None),
                    model_config_id=getattr(request, 'model_config_id', None)
                ):
                    yield f"data: {json.dumps(chunk, ensure_ascii=False)}\n\n"
            except Exception as e:
                error_chunk = {
                    "type": "error",
                    "error": str(e)
                }
                yield f"data: {json.dumps(error_chunk, ensure_ascii=False)}\n\n"
        
        return StreamingResponse(
            generate(),
            media_type="text/plain",
            headers={
                "Cache-Control": "no-cache",
                "Connection": "keep-alive",
            }
        )
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"发送消息失败: {str(e)}")


@router.post("/conversations", response_model=ConversationCreateResponse)
async def create_conversation(
    request: ConversationCreateRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """创建新对话"""
    try:
        logger.info(f"收到创建对话请求: 用户ID={current_user.id}, 标题={request.title}, 模型ID={request.model_config_id}")
        
        # 从JWT token中获取用户ID
        user_id = current_user.id
        logger.info(f"获取用户ID: {user_id}")
        
        # 验证模型配置是否存在
        if request.model_config_id:
            logger.info(f"验证模型配置: model_config_id={request.model_config_id}")
            from app.services.model_service import ModelService
            model_service = ModelService()
            model_config = model_service.get(db, request.model_config_id)
            if not model_config:
                logger.error(f"模型配置不存在: model_config_id={request.model_config_id}")
                raise HTTPException(
                    status_code=400, 
                    detail=f"模型配置不存在: model_config_id={request.model_config_id}"
                )
            if not model_config.is_active:
                logger.error(f"模型配置未激活: model_config_id={request.model_config_id}")
                raise HTTPException(
                    status_code=400, 
                    detail=f"模型配置未激活: model_config_id={request.model_config_id}"
                )
            logger.info(f"模型配置验证通过: {model_config.name}")
        
        logger.info(f"开始创建对话: user_id={user_id}, title={request.title}")
        conversation = chat_service.conversation_service.create_conversation(
            db=db,
            user_id=user_id,
            title=request.title,
            model_config_id=request.model_config_id,
            knowledge_base_id=request.knowledge_base_id,
            prompt_template_id=request.prompt_template_id
        )
        
        logger.info(f"对话创建成功: 对话ID={conversation.id}, 标题={conversation.title}")
        
        return ConversationCreateResponse(
            conversation_id=conversation.id,
            title=conversation.title,
            message="对话创建成功"
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建对话失败: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"创建对话失败: {str(e)}")


@router.get("/conversations/{conversation_id}/messages", response_model=MessageHistoryResponse)
async def get_message_history(
    conversation_id: int,
    limit: int = 50,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取消息历史"""
    try:
        # 从JWT token中获取用户ID
        user_id = current_user.id
        
        conversation = chat_service.conversation_service.get_conversation_with_messages(
            db, conversation_id, user_id
        )
        if not conversation:
            raise HTTPException(status_code=404, detail="对话不存在")
        
        messages = chat_service.conversation_service.get_conversation_messages(
            db, conversation_id, limit
        )
        
        message_list = [
            {
                "id": msg.id,
                "role": msg.role,
                "content": msg.content,
                "created_at": msg.created_at,
                "token_count": msg.token_count,
                "metadata": msg.message_metadata
            }
            for msg in messages
        ]
        
        return MessageHistoryResponse(
            messages=message_list,
            total_count=len(message_list),
            conversation_id=conversation_id
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取消息历史失败: {str(e)}")


@router.post("/rag", response_model=RAGChatResponse)
async def chat_with_rag(
    request: RAGChatRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """使用RAG进行聊天"""
    try:
        # 从JWT token中获取用户ID
        user_id = current_user.id
        
        result = await chat_service.chat_with_rag(
            db=db,
            conversation_id=request.conversation_id,
            user_id=user_id,
            message=request.message,
            knowledge_base_id=request.knowledge_base_id,
            stream=request.stream
        )
        
        return RAGChatResponse(**result)
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"RAG聊天失败: {str(e)}")


@router.get("/conversations/{conversation_id}/summary")
async def get_conversation_summary(
    conversation_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取对话摘要"""
    try:
        # 从JWT token中获取用户ID
        user_id = current_user.id
        
        summary = chat_service.get_conversation_summary(
            db=db,
            conversation_id=conversation_id,
            user_id=user_id
        )
        
        return summary
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取对话摘要失败: {str(e)}")
